﻿using GalaSoft.MvvmLight.Command;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows.Input;

namespace CuaHangBanhNgotBeoBeo.Game.ViewModel {
    class ItemViewModel : BaseViewModel {
        /// <summary>
        /// One direction
        /// </summary>
        public static int RULE_ONE_DIR = 0;

        /// <summary>
        /// To Left direction
        /// </summary>
        public static int RULE_LEFT_DIR = 1;

        /// <summary>
        /// To Right direction
        /// </summary>
        public static int RULE_RIGHT_DIR = 2;

        /// <summary>
        /// Both direction
        /// </summary>
        public static int RULE_BOTH_DIR = 7;

        /// <summary>
        /// One dot
        /// </summary>
        public static int RULE_DOT = 3;

        /// <summary>
        /// Horizontal direction
        /// </summary>
        public static int RULE_HOR = 4;

        /// <summary>
        /// Right Hexagontial 
        /// </summary>
        public static int RULE_RIGHT_HEXA = 5;

        /// <summary>
        /// Left Hexagontial 
        /// </summary>
        public static int RULE_LEFT_HEXA = 6;

        /// <summary>
        /// Rule 0
        /// </summary>
        public static int RULE_0 = (RULE_HOR | RULE_BOTH_DIR) | (RULE_RIGHT_HEXA | RULE_BOTH_DIR);

        /// <summary>
        /// Rule 1
        /// </summary>
        public static int RULE_1 = (RULE_HOR | RULE_LEFT_DIR);

        /// <summary>
        /// Rule 2
        /// </summary>
        public static int RULE_2 = (RULE_HOR | RULE_RIGHT_DIR);

        /// <summary>
        /// Rule 3
        /// </summary>
        public static int RULE_3 = (RULE_DOT);

        public override void LoadData() {
        }

        public void SetCleared() {

            foreach (var hole in _isRuled) {
                hole.State = "Normal";
            }

            _isRuled.Clear();
            if (holeactive != null) {

                if (holeactive.State.Equals("Active")) {
                    holeactive.State = "Normal";
                }

                holeactive = null;
            }

        }

        public void SetHover(Dictionary<String, Double> dic) {

            double x = 0.0d;
            dic.TryGetValue("x", out x);

            double y = 0.0d;
            dic.TryGetValue("y", out y);

            double width = 0.0d;
            dic.TryGetValue("width", out width);

            double height = 0.0d;
            dic.TryGetValue("height", out height);

            var centerX = x + width / 2.0d;
            var centerY = y + height / 2.0d;

            foreach (var hole in App.MainViewModel.HoleViewModels) {
                if (centerX + 5 >= hole.LeftPosition && centerX - 5 <= hole.LeftPosition + MainViewModel.SIZE_HOLE_WH) {
                    if (centerY + 5 >= hole.TopPosition && centerY - 5 <= hole.TopPosition + MainViewModel.SIZE_HOLE_WH) {
                        holeactive = hole;
                        break;
                    }
                }
            }

            if (holeactive != null) {
                System.Console.WriteLine("HoleActive");
                if (!holeactive.State.Equals("Filled")) {
                    int targetI = -1;
                    int targetJ = -1;

                    if (!holeactive.State.Equals("Filled"))
                        holeactive.State = "Active";
                    targetJ = holeactive.JPos;
                    targetI = holeactive.IPos;

                    int index = App.MainViewModel.HoleViewModels.IndexOf(holeactive);
                    ApplyRule(this.Rule, index, targetI, targetJ);
                }
            }
        }

        private void ApplyRule(int rule, int index, int targetI, int targetJ) {

            if (targetI >= 0 && targetJ >= 0) {

                _isRuled.Clear();

                if (rule == ItemViewModel.RULE_0) {

                    // i the same

                    int j = targetJ;

                    while (j - 1 >= 0 && App.MainViewModel.Map[targetI, j - 1] != null) {
                        if (!App.MainViewModel.Map[targetI, j - 1].State.Equals("Filled"))
                            _isRuled.Add(App.MainViewModel.Map[targetI, j-- - 1]);
                        else
                            j--;
                    }

                    j = targetJ;

                    while (j + 1 < App.MainViewModel.ColNum && App.MainViewModel.Map[targetI, j + 1] != null) {
                        if (!App.MainViewModel.Map[targetI, j + 1].State.Equals("Filled"))
                            _isRuled.Add(App.MainViewModel.Map[targetI, j++ + 1]);
                        else
                            j++;
                    }


                    // j the same

                    int i = targetI;

                    while (i - 1 >= 0 && App.MainViewModel.Map[i - 1, targetJ] != null) {
                        if (!App.MainViewModel.Map[i - 1, targetJ].State.Equals("Filled"))
                            _isRuled.Add(App.MainViewModel.Map[i-- - 1, targetJ]);
                        else
                            i--;
                    }

                    i = targetI;

                    while (i + 1 < App.MainViewModel.RowNum && App.MainViewModel.Map[i + 1, targetJ] != null) {
                        if (!App.MainViewModel.Map[i + 1, targetJ].State.Equals("Filled"))
                            _isRuled.Add(App.MainViewModel.Map[i++ + 1, targetJ]);
                        else
                            i++;
                    }

                    SetRules(targetI, targetJ);
                }

                if (rule == ItemViewModel.RULE_1) {

                    // i the same

                    int j = targetJ;

                    while (j - 1 >= 0 && App.MainViewModel.Map[targetI, j - 1] != null) {
                        if (!App.MainViewModel.Map[targetI, j - 1].State.Equals("Filled"))
                            _isRuled.Add(App.MainViewModel.Map[targetI, j-- - 1]);
                        else
                            j--;
                    }

                    SetRules(targetI, targetJ);

                }

                if (rule == ItemViewModel.RULE_2) {

                    // i the same

                    int j = targetJ;

                    while (j + 1 < App.MainViewModel.ColNum && App.MainViewModel.Map[targetI, j + 1] != null) {
                        if (!App.MainViewModel.Map[targetI, j + 1].State.Equals("Filled"))
                            _isRuled.Add(App.MainViewModel.Map[targetI, j++ + 1]);
                        else
                            j++;
                    }

                    SetRules(targetI, targetJ);
                }
            }
        }

        private void SetRules(int targetI, int targetJ) {
            foreach (var hole in App.MainViewModel.HoleViewModels) {
                if (hole.IPos == targetI && hole.JPos == targetJ) {
                    if (!hole.State.Equals("Filled"))
                        hole.State = "Active";
                }
                else {

                    if (_isRuled.Contains(hole)) {
                        if (!hole.State.Equals("Filled"))
                            hole.State = "HoverRuled";
                    }
                    else {
                        if (!hole.State.Equals("Filled"))
                            hole.State = "Normal";
                    }
                }
            }
        }

        private void SetFilled() { 

            foreach (var hole in _isRuled) {
                if (!hole.State.Equals("Active"))
                    hole.State = "Filled";
            }
        }

        public ICommand SetHoverCommand {
            get {
                if (_setHover == null) {
                    _setHover = new RelayCommand<Dictionary<String, Double>>((param) => SetHover(param));
                }
                return _setHover;
            }
        }

        public ICommand SetFilledCommand {
            get {
                if (_setFilled == null) {
                    _setFilled = new RelayCommand(() => SetFilled());
                }
                return _setFilled;
            }
        }

        public ICommand SetClearedCommand {
            get {
                if (_setCleared == null) {
                    _setCleared = new RelayCommand(() => SetCleared());
                }
                return _setCleared;
            }
        }

        private RelayCommand<Dictionary<String, Double>> _setHover;

        private RelayCommand _setFilled;

        private RelayCommand _setCleared;

        private int _rule;

        public int Rule {
            get { return _rule; }
            set {
                _rule = value;
                NotifyPropertyChanged("Rule");
            }
        }

        private List<HoleViewModel> _isRuled = new List<HoleViewModel>();

        private HoleViewModel holeactive = null;

    }
}
